/*
 * light.h
 *
 *  Created on: 25-jun-2009
 *      Author: HPK
 */

#ifndef LIGHT_H_
#define LIGHT_H_

#include "point.h"
#include "objectModel/rgbaColor.h"
#include <GL/gl.h>

class Light{
	private:
		Point _position;

		RGBAColor _diffuse;
		RGBAColor _ambient;

		float _constantAttenuation;
		float _linearAttenuation;
		float _quadraticAttenuation;

		bool _enabled;

		float _brightness;
		float _distance;
	public:
		Light(){
			_enabled=false;
			_on=false;
		}

		Light(const Point& pos,RGBAColor diffuse,RGBAColor ambient,float cA=1.0f,float lA=0.0f,float qA=0.0f){
			_position=pos;
			_diffuse=diffuse;
			_ambient=ambient;
			_constantAttenuation=cA;
			_linearAttenuation=lA;
			_quadraticAttenuation=qA;
			_enabled=false;
			_on=false;
		}
		virtual ~Light(){}

		const Point& position()const{ return _position; }
		const float* positionPtr()const{ return (float*)&_position; }
		void position(const Point& pos){ _position=pos; }

		const RGBAColor& diffuseRGBA()const{ return _diffuse; }
		const float* diffuse()const{ return (float*)&_diffuse; }
		void diffuse(const RGBAColor& diffuse){ _diffuse=diffuse; }

		const RGBAColor& ambientRGBA()const{ return _ambient; }
		const float* ambient()const{ return (float*)&_ambient; }
		void ambient(const RGBAColor& ambient){ _ambient=ambient; }

		float linearAttenuation()const{ return _linearAttenuation; }
		void linearAttenuation(float lA){ _linearAttenuation=lA; }

		float constantAttenuation()const{ return _constantAttenuation; }
		void constantAttenuation(float cA){ _constantAttenuation=cA; }

		float quadraticAttenuation()const{ return _quadraticAttenuation; }
		void quadraticAttenuation(float qA){ _quadraticAttenuation=qA; }

		bool enabled()const{ return _enabled; }

		float brightness()const{ return _brightness; }
		void brightness(float val){ _brightness=val; }

		float distance()const{ return _distance; }
		void distance(float val){_distance = val;}

		void enable(){ _enabled=true; }
		void disable(){
			_enabled=false;
			if(_on)
				off();
		}

	protected:
		friend class Lighting;
		unsigned int hwlightId;
		bool _on;

		virtual void on(unsigned int j){
			if(!_on){
				hwlightId = j;

				glLightfv(GL_LIGHT0+j, GL_POSITION, positionPtr());
				glLightfv(GL_LIGHT0+j, GL_DIFFUSE, diffuse());
				glLightfv(GL_LIGHT0+j, GL_AMBIENT, ambient());
				glLightf(GL_LIGHT0+j, GL_CONSTANT_ATTENUATION, constantAttenuation());
				glLightf(GL_LIGHT0+j, GL_LINEAR_ATTENUATION, linearAttenuation());
				glLightf(GL_LIGHT0+j, GL_QUADRATIC_ATTENUATION, quadraticAttenuation());
				glEnable(GL_LIGHT0+j);

				_on=true;
			}
		}

		void off(){
			if(_on){
				glDisable(GL_LIGHT0+hwlightId);
				_on=false;
			}
		}
};

class LightCompare{
	public:
		bool operator()(const Light* l1,const Light* l2)const{
			if(l1->brightness()==l2->brightness())
				return(l1->distance()>l2->distance());
			else
				return l1->brightness()<l2->brightness();
		}
};


#endif /* LIGHT_H_ */
